package com.qyy.remotemonitor.model.presenter.remotemonitor;

import android.Manifest;
import android.app.Application;
import android.content.ContentResolver;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.provider.CallLog;
import android.support.v4.app.ActivityCompat;

import com.blankj.utilcode.util.LogUtils;
import com.qyy.remotemonitor.MyApplication;
import com.qyy.remotemonitor.common.mvp.BasePresenter;
import com.qyy.remotemonitor.common.rx.CommonSubscriber;
import com.qyy.remotemonitor.common.rx.RxUtil;
import com.qyy.remotemonitor.common.util.LocationManagerUtil;
import com.qyy.remotemonitor.dao.bean.CallHistoryBean;
import com.qyy.remotemonitor.http.ApiService;
import com.qyy.remotemonitor.http.bean.HttpOperationBean;
import com.qyy.remotemonitor.http.bean.HttpUploadCallRecordsBean;
import com.qyy.remotemonitor.http.bean.HttpUploadLocationBean;
import com.qyy.remotemonitor.http.params.HttpUploadCallRecordsParam;
import com.qyy.remotemonitor.http.params.HttpUploadLocationParam;
import com.qyy.remotemonitor.model.contract.remotemonitor.RemoteMonitorContract;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.Nonnull;
import javax.inject.Inject;

import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
import io.reactivex.FlowableEmitter;
import io.reactivex.FlowableOnSubscribe;
import io.reactivex.functions.Consumer;
import io.realm.Realm;
import io.realm.RealmResults;
import io.realm.Sort;

/**
 * Created by qinyy on 2018/10/5.
 */

public class RemoteMonitorPresenter extends BasePresenter<RemoteMonitorContract.View>
        implements RemoteMonitorContract.Presenter
{
    // 数据库读写线程同步锁
    private Object mSyncLock = new Object();
    @Inject ApiService apiService;

    @Inject public RemoteMonitorPresenter()
    {

    }

    @Override public void queryOperation()
    {
        addSubscribe(apiService.queryOperation()
                .compose(RxUtil.rxSchedulerHelper())
                .compose(RxUtil.handleHttpResult(HttpOperationBean.class))
                .doOnNext(new Consumer<HttpOperationBean>()
                {
                    @Override public void accept(HttpOperationBean bean) throws Exception
                    {
                        // 每次调用onNext之前都会调用一下这个方法
                    }
                }).subscribeWith(new CommonSubscriber<HttpOperationBean>(getView())
                {
                    @Override public void onNext(HttpOperationBean bean)
                    {
                        getView().queryOperationSuccess(bean);
                    }

                    // 如果需要对失败特殊处理，则重写onError,否则使用封装好的报错处理，直接调用baseview中的showError
                    @Override public void onError(Throwable e)
                    {
                        getView().queryOperationFailure("", e.getMessage());
                    }
                }));
    }

    @Override public void writeOperationDone(String id)
    {

    }

    @Override public void initLocation(@Nonnull Application context)
    {
        LocationManagerUtil.getInstance(context);
    }

    @Override public void uploadLocation(double lat, double lon, int operatorId)
    {
        HttpUploadLocationParam param = new HttpUploadLocationParam();
        param.setOperationId(operatorId);
        param.setLat(lat);
        param.setLon(lon);
        addSubscribe(apiService.uploadLocation(convertPostBody(param))
                .compose(RxUtil.rxSchedulerHelper())
                .compose(RxUtil.handleHttpResult(HttpUploadLocationBean.class))
                .doOnNext(new Consumer<HttpUploadLocationBean>()
                {
                    @Override public void accept(HttpUploadLocationBean bean) throws Exception
                    {
                        // 每次调用onNext之前都会调用一下这个方法
                    }
                }).subscribeWith(new CommonSubscriber<HttpUploadLocationBean>(getView())
                {
                    @Override public void onNext(HttpUploadLocationBean bean)
                    {
                        LogUtils.d("upload location success!");
                    }

                    // 如果需要对失败特殊处理，则重写onError,否则使用封装好的报错处理，直接调用baseview中的showError
                    @Override public void onError(Throwable e)
                    {
                        LogUtils.e("upload location failure!" + e.getMessage());
                    }
                }));
    }

    @Override public void updateCallsHistory()
    {
        addSubscribe(Flowable.create(new FlowableOnSubscribe<String>()
        {
            @Override public void subscribe(FlowableEmitter<String> e) throws Exception
            {
                // 获取数据库中最新一条通话记录的时间，避免重复插入
                synchronized (mSyncLock)
                {
                    Realm realm = Realm.getDefaultInstance();
                    RealmResults<CallHistoryBean> realmResults = realm.where(CallHistoryBean.class)
                            .findAllSorted("time", Sort.DESCENDING);
                    long lastCallTime = -1;
                    if (realmResults != null && realmResults.size() > 0)
                    {
                        LogUtils.d("数据库中存有" + realmResults.size() + "条通话记录");
                        lastCallTime = realmResults.get(0).getTime();
                        String date = new SimpleDateFormat("yyyy-MM-dd HH：mm：ss")
                                .format(new Date(lastCallTime));
                        LogUtils.d("最新一条记录时间是" + date);
                    }
                    else
                    {
                        LogUtils.d("数据库中没有通话记录");
                    }
                    ContentResolver resolver = MyApplication.getInstance().getContentResolver();
                    if (ActivityCompat.checkSelfPermission(MyApplication.getInstance(),
                            Manifest.permission.READ_CALL_LOG) == PackageManager.PERMISSION_GRANTED)
                    {
                        Cursor cursor = resolver.query(CallLog.Calls.CONTENT_URI, // 查询通话记录的URI
                                new String[]{CallLog.Calls.CACHED_NAME// 通话记录的联系人
                                        , CallLog.Calls.NUMBER// 通话记录的电话号码
                                        , CallLog.Calls.DATE// 通话记录的日期
                                        , CallLog.Calls.DURATION// 通话时长
                                        , CallLog.Calls.TYPE}// 通话类型
                                , null, null, CallLog.Calls.DEFAULT_SORT_ORDER// 按照时间逆序排列，最近打的最先显示
                        );
                        // 3.通过Cursor获得数据
                        List<Map<String, String>> list = new ArrayList<Map<String, String>>();
                        while (cursor.moveToNext())
                        {
                            String name = cursor.getString(
                                    cursor.getColumnIndex(CallLog.Calls.CACHED_NAME));
                            String number =
                                    cursor.getString(cursor.getColumnIndex(CallLog.Calls.NUMBER));
                            long dateLong =
                                    cursor.getLong(cursor.getColumnIndex(CallLog.Calls.DATE));
                            int duration =
                                    cursor.getInt(cursor.getColumnIndex(CallLog.Calls.DURATION));
                            int type = cursor.getInt(cursor.getColumnIndex(CallLog.Calls.TYPE));
                            String typeString = "";
                            switch (type)
                            {
                                case CallLog.Calls.INCOMING_TYPE:
                                    typeString = "打入";
                                    break;
                                case CallLog.Calls.OUTGOING_TYPE:
                                    typeString = "打出";
                                    break;
                                case CallLog.Calls.MISSED_TYPE:
                                    typeString = "未接";
                                    break;
                                default:
                                    break;
                            }
                            if (dateLong > lastCallTime)
                            {
                                CallHistoryBean bean = new CallHistoryBean();
                                bean.setDuration((duration / 60) + "分钟" + (duration % 60) + "秒");
                                bean.setName((name == null) ? "未备注联系人" : name);
                                bean.setNum(number);
                                bean.setTime(dateLong);
                                bean.setType(typeString);
                                realm.beginTransaction();
                                realm.insert(bean);
                                realm.commitTransaction();
                                LogUtils.d("插入一条新记录" + new SimpleDateFormat("yyyy-MM-dd HH-mm-ss")
                                        .format(new Date(dateLong)));
                            }
                        }
                        return;
                    }
                    else
                    {
                        LogUtils.d("没有读取通话记录权限");
                    }
                }
                e.onNext("");
                e.onComplete();
                //    Thread.currentThread().interrupt();
            }
        }, BackpressureStrategy.BUFFER).compose(RxUtil.rxSchedulerHelper())
                .doOnNext(new Consumer<String>()
                {
                    @Override public void accept(String bean) throws Exception
                    {
                        // 每次调用onNext之前都会调用一下这个方法
                    }
                }).subscribeWith(new CommonSubscriber<String>(getView())
                {
                    @Override public void onNext(String o)
                    {

                    }

                    // 如果需要对失败特殊处理，则重写onError,否则使用封装好的报错处理，直接调用baseview中的showError
                    @Override public void onError(Throwable e)
                    {

                    }
                }));
    }


    @Override public void uploadCallRecord(final long beginDate, final long endDate, final int operatorId)
    {
        LogUtils.d("上传通话记录前，先读取数据库中的通话记录");
        Realm realm = Realm.getDefaultInstance();
        realm.where(CallHistoryBean.class).findAllSortedAsync("time", Sort.DESCENDING).asFlowable()
                .filter(results -> results.isLoaded())
             /*   .filter(new Predicate<RealmResults<CallHistoryBean>>()
                {
                    @Override public boolean test(RealmResults<CallHistoryBean> callHistoryBeans)
                            throws Exception
                    {
                        return callHistoryBeans.isLoaded();
                    }
                })*/
                .map(realm::copyFromRealm)
                .subscribeWith(new CommonSubscriber<List<CallHistoryBean>>(getView())
                {
                    @Override public void onNext(List<CallHistoryBean> callHistoryBeans)
                    {
                        // 查询数据库中所有的通话记录
                        synchronized (mSyncLock)
                        {
                            if (callHistoryBeans != null && callHistoryBeans.size() > 0)
                            {
                                LogUtils.d("数据库中存有" + callHistoryBeans.size() + "条通话记录");
                                // 上传
                                HttpUploadCallRecordsParam param = new HttpUploadCallRecordsParam();
                                param.setCallRecordsList(
                                        new ArrayList<HttpUploadCallRecordsParam.CallRecords>());
                                for (CallHistoryBean _b : callHistoryBeans)
                                {
                                    if (beginDate <= _b.getTime() &&
                                            _b.getTime() <= (endDate + 60 * 60 * 24 * 1000))
                                    {
                                        HttpUploadCallRecordsParam.CallRecords record =
                                                param.new CallRecords();
                                        record.setBegintime(_b.getTime());
                                        record.setType(_b.getType());
                                        record.setDuration(_b.getDuration());
                                        record.setCallnum(_b.getNum());
                                        record.setContactname(_b.getName());
                                       // record.setRecordsid(_b.getTime());
                                        param.getCallRecordsList().add(record);
                                    }

                                }
                                param.setOperationid(operatorId);
                                addSubscribe(apiService.uploadCallRecords(convertPostBody(param))
                                        .compose(
                                                RxUtil.rxSchedulerHelper())
                                        .compose(
                                                RxUtil.handleHttpResult(HttpUploadCallRecordsBean.class))
                                        .doOnNext(new Consumer<HttpUploadCallRecordsBean>()
                                        {
                                            @Override
                                            public void accept(HttpUploadCallRecordsBean bean)
                                                    throws Exception
                                            {
                                                // 每次调用onNext之前都会调用一下这个方法
                                            }
                                        }).subscribeWith(
                                                new CommonSubscriber<HttpUploadCallRecordsBean>(
                                                        getView())
                                                {
                                                    @Override public void onNext(
                                                            HttpUploadCallRecordsBean bean)
                                                    {
                                                        LogUtils.d("上传通话记录成功");
                                                    }

                                                    // 如果需要对失败特殊处理，则重写onError,否则使用封装好的报错处理，直接调用baseview中的showError
                                                    @Override public void onError(Throwable e)
                                                    {
                                                        LogUtils.e("上传通话记录失败 " + e.getMessage());
                                                    }
                                                }));
                            }
                            else
                            {
                                LogUtils.d("数据库中没有通话记录");
                            }
                        }
                    }
                });
    }
}
